package com.fy.oa.zc.rest;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fy.oa.zc.exception.FyOAException;
import com.seeyon.client.CTPRestClient;
import com.seeyon.client.CTPServiceClientManager;

public class FyOARestClientImpl implements FyOARestClient {
	private String userName;
	private String password;
	private String path;
	private static final String FORMXMLTEMPLATE = "<forms version=\"2.1\">\n" + "  <formExport>\n"
			+ "    <summary id=\"-1\" name=\"\"/>\n" + "    <definitions/>\n" + "    <values>\n"
			+ "      <column name=\"描述\">\n" + "        <value></value>\n" + "      </column>\n"
			+ "      <column name=\"summaryid\">\n" + "        <value></value>\n" + "      </column>\n"
			+ "      <column name=\"时间\">\n" + "        <value></value>\n" + "      </column>\n" + "    </values>\n"
			+ "    <subForms/>\n" + "  </formExport>\n" + "</forms>";

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.fy.oa.zc.rest.FyOARestClient#setUserName(java.lang.String)
	 */
	@Override
	public void setUserName(String userName) {
		this.userName = userName;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.fy.oa.zc.rest.FyOARestClient#setPassword(java.lang.String)
	 */
	@Override
	public void setPassword(String password) {
		this.password = password;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.fy.oa.zc.rest.FyOARestClient#setPath(java.lang.String)
	 */
	@Override
	public void setPath(String path) {
		this.path = path;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.fy.oa.zc.rest.FyOARestClient#getRestClient()
	 */
	@Override
	public CTPRestClient getRestClient() {
		try {
			CTPServiceClientManager clientManager = CTPServiceClientManager.getInstance(path);
			// 取得REST动态客户机实例
			CTPRestClient client = clientManager.getRestClient();
			client.authenticate(userName, password);
			return client;
		} catch (Exception e) {
			throw new FyOAException("获取restClient 发生异常", e);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.fy.oa.zc.rest.FyOARestClient#getFormValues(long, java.util.Map)
	 */
	@Override
	public Map<String, String> getFormValues(long summaryid, Set<String> nameSet) {
		if (nameSet.size() > 0) {
			String result = getRestClient().get("flow/data/" + summaryid, String.class);
			System.out.println(result);
			if (result != null && !"".equals(result)) {
				Document doc = null;
				try {
					doc = DocumentHelper.parseText(result);
				} catch (DocumentException e1) {
					throw new FyOAException("解析导出的表单数据XML文件发生异常", e1);
				}
				List<?> list = doc.selectNodes("//values//column");
				Map<String, String> valueMap = new HashMap<String, String>();
				for (int i = 0; i < list.size(); i++) {
					Element e = (Element) list.get(i);
					String name = e.attributeValue("name");
					String value = ((Element) e.elements().get(0)).getText().replace("<![CDATA[", "").replace("]]>",
							"");
					if (nameSet.contains(name)) {
						valueMap.put(name, value);
					}
				}
				return valueMap;
			}
		}
		return null;
	}

	@Override
	public boolean formImport(String message, String loginName, long summaryid) throws DocumentException {
		Document doc = DocumentHelper.parseText(FORMXMLTEMPLATE);
		List<?> list = doc.selectNodes("//value");
		if (list.size() == 3) {
			((Element) list.get(0)).setText(message);
			((Element) list.get(1)).setText(String.valueOf(summaryid));
			((Element) list.get(2))
					.setText((new Timestamp(Calendar.getInstance().getTimeInMillis())).toString().substring(0, 19));
			Map<String, String> res = new HashMap<String, String>();
			res.put("loginName", loginName);
			res.put("dataXml", doc.asXML());
			return "1".equals(getRestClient().post("form/import/errorlogform", res, String.class));
		}
		return false;
	}

	@Override
	public boolean sendMessage(String message, long[] userArray) {
		return false;
	}

	@Override
	public String getToken() {
		CTPServiceClientManager clientManager = CTPServiceClientManager.getInstance(path);
		// 取得REST动态客户机实例
		CTPRestClient client = clientManager.getRestClient();
		String result = client.get("token/" + userName + "/" + password, String.class);
		ObjectMapper mapper = new ObjectMapper();
		try {
			Map<?, ?> map = mapper.readValue(result, Map.class);
			return (String) map.get("id");
		} catch (JsonParseException e) {
			throw new FyOAException("获取Token发生异常", e);
		} catch (JsonMappingException e) {
			throw new FyOAException("获取Token发生异常", e);
		} catch (IOException e) {
			throw new FyOAException("获取Token发生异常", e);
		}
	}

	@Override
	public InputStream download(String fileID) {
		try {
			URL url = new URL(path + "/seeyon/services/downloadService?token=" + getToken() + "&fileId=" + fileID);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setDoInput(true);
			InputStream is = conn.getInputStream();
			return is;
		} catch (MalformedURLException e) {
			throw new FyOAException("下载文件发生异常", e);
		} catch (IOException e1) {
			throw new FyOAException("下载文件发生异常", e1);
		}
	}

	@Override
	public String upload(byte[] fileBytes, String fileName) {
		try {
			CTPRestClient client = getRestClient();
			String token = client.get("/token/" + userName + "/" + password, String.class, "text/plain");
			java.net.URL url = new java.net.URL(
					this.path + "/seeyon/uploadService.do?method=processUploadService&token=" + token
							+ "&senderLoginName=002218");

			String BOUNDARY = "---------10086"; // 定义数据分隔线

			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			// 发送POST请求必须设置如下两行

			conn.setDoOutput(true);

			conn.setDoInput(true);

			conn.setUseCaches(false);

			conn.setRequestMethod("POST");

			conn.setRequestProperty("connection", "Keep-Alive");

			conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");

			conn.setRequestProperty("Charsert", "UTF-8");

			conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);

			OutputStream out = new DataOutputStream(conn.getOutputStream());

			byte[] end_data = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();// 定义最后数据分隔线

			// File file = new File(fname);

			StringBuilder sb = new StringBuilder();

			sb.append("--");

			sb.append(BOUNDARY);

			sb.append("\r\n");

			sb.append("Content-Disposition: form-data;name=\"file1\";filename=\"" + fileName + "\"\r\n");

			sb.append("Content-Type:application/octet-stream\r\n\r\n");

			byte[] data = sb.toString().getBytes("UTF-8");

			out.write(data);
			out.write(fileBytes);
			// DataInputStream in = new DataInputStream(new
			// FileInputStream(file));

			// int bytes = 0;
			//
			// byte[] bufferOut = new byte[1024];
			//
			// while ((bytes = in.read(bufferOut)) != -1) {
			//
			// out.write(bufferOut, 0, bytes);
			//
			// }

			out.write("\r\n".getBytes()); // 多个文件时，二个文件之间加入这个

			// in.close();

			out.write(end_data);

			out.flush();

			out.close();
			// 定义BufferedReader输入流来读取URL的响应

			BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));

			String line = null;
			StringBuilder temp = new StringBuilder();
			while ((line = reader.readLine()) != null) {
				temp.append(line);
			}
			return temp.toString();

		} catch (Exception e) {
			// System.out.println("发送POST请求出现异常！" + e);
			throw new FyOAException("上传文件发生异常", e);
		}
	}

	@Override
	public FyOARestValuesBean getFormValues(long summaryid, Set<String> fieldNameSet, Set<String> repeatFieldNameSet) {
		if ((fieldNameSet != null && fieldNameSet.size() > 0
				|| repeatFieldNameSet != null && repeatFieldNameSet.size() > 0)) {
			String result = getRestClient().get("flow/data/" + summaryid + "?exportType=1", String.class);
			System.out.println(">>>>>>>" + result);
			if (result != null && !"".equals(result)) {
				Document doc = null;
				try {
					doc = DocumentHelper.parseText(result);
				} catch (DocumentException e1) {
					throw new FyOAException("解析导出的表单数据XML文件发生异常", e1);
				}
				List<?> list = doc.selectNodes("//values//column");
				FyOARestValuesBean values = new FyOARestValuesBean();
				for (int i = 0; i < list.size(); i++) {
					Element e = (Element) list.get(i);
					String name = e.attributeValue("name");
					String value = ((Element) e.elements().get(0)).getText().replace("<![CDATA[", "").replace("]]>",
							"");
					if (fieldNameSet != null && fieldNameSet.contains(name)) {
						values.setValues(name, value);
					} else if (repeatFieldNameSet != null && repeatFieldNameSet.contains(name)) {
						values.setRepeatValues(name, value);
					}
				}
				return values;
			}
		}
		return null;
	}

}
